<template>
    <div class="flow-chart-wrap">
        <nav class="flow-nav__btn">
            <Button type="info">流程信息</Button>
            <Button type="success">保存</Button>
            <Button type="warning">导出</Button>
            <Button type="error" @click="clearJsplumb">清空画布</Button>
        </nav>
        <main class="flow-module__main">
            <Menus @on-drag-end="onDragEnd" :menuList="menuList"></Menus>
            <div id="jsplumbEditorId" ref="jsplumbEditorRef" class="flow-content__editor">
                <div 
                    :class="['jsplumb-node', { 'is-actived': currentIndex === index }]" 
                    v-for="(item, index) in flowData" 
                    :key="item.id"
                    :id="item.id"
                    :data-index="index"
                    :style="{ left: item.left, top: item.top, '--color--': item.color }"
                    @click.stop="selectedNode(item, index)"
                    @contextmenu.stop="handleAction($event, item, index)"
                >
                    <Icon :type="item.icon" :color="item.color" size='22'/>
                    <div class="node__content">{{ item.label }}</div>
                    <Icon type="ios-link" class="flow-node-drag"/>
                    <Dropdown trigger="custom" :visible="item.isAction" style="margin-left: 20px">
                        <template #list>
                            <DropdownMenu>
                                <DropdownItem> 
                                    <span @click="removeFlowNode">删除节点</span>
                                </DropdownItem>
                                <DropdownItem @click="onEditNode">编辑节点</DropdownItem>
                            </DropdownMenu>
                        </template>
                    </Dropdown>
                </div>
            </div>
        </main>

        <!-- 配置右键菜单 -->
        <!-- <Dropdowns :visible="dropVisible" :style="styleOptions" @on-edit-node="onEditNode" @on-remove-node="removeFlowNode"></Dropdowns> -->
        <!-- 编辑节点内容 -->
        <!-- <EditNode @on-update="onUpdateNode" :visible="editVisible" :data="currentData" ref="EditNodeRef"></EditNode> -->
    </div>
</template>

<script setup lang="js" name="FlowChart">
import { jsPlumb, jsPlumbUtil } from 'jsplumb';
import { Message } from 'view-ui-plus';
import Node from './node';
import { defaultConfig } from './config';
import Dropdowns from "./Dropdowns.vue";
import Menus from './Menus.vue';
import { list } from './templates';
import EditNode from './drawer/EditNode.vue';

const dropVisible = ref(false)
const styleOptions = reactive({
    position: 'absolute',
    left: '0px',
    top: '0px'
})
const currentIndex = ref(-1)
const jsPlumbInstance = ref(null)
const jsplumbEditorRef = ref(null)
const flowData = ref([])
const menuList = reactive(list)
const EditNodeRef = ref(null)
const editVisible = ref(false)
const currentData = ref({})

// 拖拽结束事件
const onDragEnd = (evt) => {
    // 拖拽结束节点位置
    const { originalEvent: { clientX, clientY }, item, oldIndex } = evt
    let node_left = clientX, node_top = clientY;
    // 拖拽对象信息
    const { icon, color } = menuList[oldIndex]
    // 获取jsplumb容器信息
    const plumbContainer = jsplumbEditorRef.value
    const { left, top, width, height} = plumbContainer.getBoundingClientRect()
    // 判断拖拽对象是否在容器内，否则提示
    if (clientX > left && clientX < left+width && clientY > top && clientY < top+height) {
        const uniqueId = "node_id_"+flowData.value.length
        node_left = node_left - left + plumbContainer.scrollLeft
        node_top = node_top - top + plumbContainer.scrollTop
        node_left -= 85;
        node_top -= 16;
        flowData.value.push(new Node(uniqueId,item.innerText, icon, color, { left: `${node_left}px`, top: `${node_top}px` }, false))
       
        // jsplumb配置当前拖拽节点，拖拽才会生效
        nextTick(() => {
            jsPlumbInstance.value.makeSource(uniqueId, defaultConfig.sourceOptions)
            jsPlumbInstance.value.makeTarget(uniqueId, defaultConfig.targetOptions)
            jsPlumbInstance.value.draggable(uniqueId, {
                containment: 'parent',
                stop: function ({ drag, e, el, pos }) {
                    // 拖拽节点结束，更新数据位置，放置二次渲染位置异常
                    const dataIndex = el.getAttribute('data-index')
                    const currentNode = flowData.value[dataIndex]
                    currentNode.left = pos[0]
                    currentNode.top = pos[1]
                }
            })
        })
    } else {
        Message.warning({
            content: '请将模块拖动到编辑区域',
            duration: 3,
            background: true,
            closable: false
        });
    }
}

// 清空画布
const clearJsplumb = () => {
    flowData.value = []
    jsPlumbInstance.value.reset()
}

// 右键菜单
const handleAction = (evt, item, index) => {
    currentIndex.value = index
    // 阻止默认右键菜单
    evt.preventDefault();
    flowData.value.forEach(el => {
        if (el.id == item.id) el.isAction = true
        else el.isAction = false
    })
    const { clientX, clientY } = evt
    styleOptions.left =`${clientX}px`
    styleOptions.top = `${clientY}px`
}

// 初始化jsplumb，包括端点，连线方式，锚点
const initJsPlumbMap = () => {
    jsPlumbInstance.value.ready(() => {
        // 导入默认配置
        jsPlumbInstance.value.importDefaults(defaultConfig.setting)
        // 会使整个jsPlumb立即重绘
        jsPlumbInstance.value.setSuspendDrawing(false, true)

        // 单击连接线事件
        jsPlumbInstance.value.bind('click', function (line, originalEvent) {
            jsPlumbInstance.value.deleteConnection(line)
        })

        // 重置容器
        jsPlumbInstance.value.setContainer(jsplumbEditorRef.value)
   })
}

nextTick(() => {
    // 监听线条拖拽事件
    jsPlumbInstance.value.bind('connectionDrag', function (line) {
        console.log(33333);
    })
})

// 删除节点
const removeFlowNode = (nodeId) => {
    nodeId = flowData.value[currentIndex.value].id
    dropVisible.value = false
    jsPlumbInstance.value.remove(nodeId)
}

// 编辑节点
const onEditNode = (nodeId) => {
    currentData.value = JSON.parse(JSON.stringify(flowData.value[currentIndex.value]))
    nextTick(() => {
        editVisible.value = !editVisible.value
        dropVisible.value = false
    })
}

// 更新对象
const onUpdateNode = data => {
    const findIndex = flowData.value.findIndex(el => el.id === data.id)
    if (findIndex !== -1) flowData.value[findIndex] = data
    editVisible.value = false
}

// 选中当前节点
const selectedNode = (item, index) => {
    currentIndex.value = index
    dropVisible.value = false
}

onMounted(() => {
    jsPlumbInstance.value = jsPlumb.getInstance()
    nextTick(() => {
        initJsPlumbMap()
    })
})
</script>

<style lang="scss" src="./style.scss"></style>